﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Xml;
using SHomeWorkshop.LunarPresentation.Interfaces;
using SHomeWorkshop.LunarPresentation.Widegets;

namespace SHomeWorkshop.LunarPresentation.Expressions
{
    public class Bracket : MSExpression, IDirection, ICollapsed
    {
        public Bracket(SubPanel rootPanel, SubPanel parentPanel, Editor editor)
            : base(rootPanel, parentPanel, editor)
        {
            // 基类构造方法会调用“InitializeMSPanels”这个虚方法。
            this.SizeChanged += new SizeChangedEventHandler(Bracket_SizeChanged);

            this.chineseName = "括弧式";

            bPanel.MouseLeftButtonDown +=
                new System.Windows.Input.MouseButtonEventHandler(bPanel_MouseLeftButtonDown);
            bPanel.MouseLeftButtonUp +=
                new System.Windows.Input.MouseButtonEventHandler(bPanel_MouseLeftButtonUp);

            bPanel.MouseRightButtonDown += new System.Windows.Input.MouseButtonEventHandler(bPanel_MouseRightButtonDown);
        }

        void bPanel_MouseRightButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            if (Editor == null) return;
            Editor.SelectedExpression = this;
            e.Handled = true;
        }

        void bPanel_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            // 接收拖动来的公式。
            Globals.DropExpression(this);
        }

        void bPanel_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            if (Editor == null) return;
            Editor.SelectedExpression = this;

            //准备拖动公式。
            Globals.dragSourceExpression = this;
            e.Handled = true;
        }

        private BracketPanel bPanel;

        public BracketPanel BPanel
        {
            get { return bPanel; }
        }

        public Orientation Direction
        {
            get
            {
                if (this.basePanel != null)
                {
                    return this.basePanel.Orientation;
                }
                else return Orientation.Horizontal;
            }

            set
            {
                this.basePanel.Orientation = value;
                this.XmlData.SetAttribute("Orientation", value.ToString());
                RefreshSubPanelRelatios();
                this.Editor.IsModified = true;
            }
        }

        void Bracket_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            if (this.basePanel.Orientation == Orientation.Horizontal)
            {
                if (this.masterPanel.ActualHeight > this.slavePanel.ActualHeight)
                {
                    if (this.bPanel.Location != BracketPanel.BracketLocation.Right)
                    {
                        this.bPanel.Location = BracketPanel.BracketLocation.Right;
                    }
                }
                else if (this.masterPanel.ActualHeight < this.slavePanel.ActualHeight)
                {
                    if (this.bPanel.Location != BracketPanel.BracketLocation.Left)
                    {
                        this.bPanel.Location = BracketPanel.BracketLocation.Left;
                    }
                }
                else //高度相等时，看子面板中公式的数量。
                {
                    if (this.masterPanel.BasePanel.Children.Count >
                        this.slavePanel.BasePanel.Children.Count)
                    {
                        if (this.bPanel.Location != BracketPanel.BracketLocation.Right)
                        {
                            this.bPanel.Location = BracketPanel.BracketLocation.Right;
                        }
                    }
                    else
                    {
                        if (this.bPanel.Location != BracketPanel.BracketLocation.Left)
                        {
                            this.bPanel.Location = BracketPanel.BracketLocation.Left;
                        }
                    }
                }
            }
            else // 在垂直排列的括弧式中。
            {
                if (this.masterPanel.ActualWidth > this.slavePanel.ActualWidth)
                {
                    if (this.bPanel.Location != BracketPanel.BracketLocation.Bottom)
                    {
                        this.bPanel.Location = BracketPanel.BracketLocation.Bottom;
                    }
                }
                else if (this.masterPanel.ActualWidth < this.slavePanel.ActualWidth)
                {
                    if (this.bPanel.Location != BracketPanel.BracketLocation.Top)
                    {
                        this.bPanel.Location = BracketPanel.BracketLocation.Top;
                    }
                }
                else //宽度相等时，看子面板中公式的数量。
                {
                    if (this.masterPanel.BasePanel.Children.Count >
                        this.slavePanel.BasePanel.Children.Count)
                    {
                        if (this.bPanel.Location != BracketPanel.BracketLocation.Bottom)
                        {
                            this.bPanel.Location = BracketPanel.BracketLocation.Bottom;
                        }
                    }
                    else
                    {
                        if (this.bPanel.Location != BracketPanel.BracketLocation.Top)
                        {
                            this.bPanel.Location = BracketPanel.BracketLocation.Top;
                        }
                    }
                }
            }
        }

        protected override void InitializeMSPanels(SubPanel rootPanel, Editor editor)
        {
            this.basePanel.Orientation = Orientation.Horizontal;

            this.masterPanel = new SubPanel(rootPanel, null, editor, this);
            this.masterPanel.VerticalAlignment = VerticalAlignment.Center;
            this.masterPanel.HorizontalAlignment = HorizontalAlignment.Center;
            this.basePanel.Children.Add(this.masterPanel);

            // 括弧画板。
            bPanel = new BracketPanel();
            //bPanel.MouseDown += new System.Windows.Input.MouseButtonEventHandler(bPanel_MouseDown);
            this.basePanel.Children.Add(bPanel);
            bPanel.Foreground = ExForeground;

            this.slavePanel = new SubPanel(rootPanel, null, editor, this);
            this.slavePanel.VerticalAlignment = VerticalAlignment.Center;
            this.slavePanel.HorizontalAlignment = HorizontalAlignment.Center;
            this.basePanel.Children.Add(this.slavePanel);

            RefreshSubPanelRelatios();
        }

        public override Brush ExForeground
        {
            get
            {
                return base.ExForeground;
            }
            set
            {
                UpdateExForegroundWithoutXmlChanging(value);
                UpdateExForegroundToXmlData(value);
                Editor.IsModified = true;
            }
        }

        public override void UpdateExForegroundWithoutXmlChanging(Brush value)
        {
            base.UpdateExForegroundWithoutXmlChanging(value);

            base.exForeground = value;
            this.bPanel.Foreground = value;

            if (this.exCollapseMark != null)
            {
                this.exCollapseMark.UpdateForeground();
            }
        }

        protected override void BuildChildren()
        {
            base.BuildChildren();

            if (this.XmlData == null) return;

            // 读取、建立括弧式相关内容。

            XmlNodeList panelNodes = this.XmlData.SelectNodes("Expression");
            foreach (XmlNode node in panelNodes)
            {
                if (node.GetAttributeString("Type") == TypeOfExpression.SubPanel.ToString()
                    && node.GetAttributeString("Location") == "Master")
                {
                    this.masterPanel.XmlData = node;
                }
                else if (node.GetAttributeString("Type") == TypeOfExpression.SubPanel.ToString()
                   && node.GetAttributeString("Location") == "Slave")
                {
                    this.slavePanel.XmlData = node;
                }
            }

            XmlAttribute attrOfOrientation = this.XmlData.GetAttribute("Orientation");
            if (attrOfOrientation != null)
            {
                this.basePanel.Orientation = (Orientation)Enum.Parse(typeof(Orientation), attrOfOrientation.Value);
            }

            XmlAttribute attrIsCollapsed = this.XmlData.GetAttribute("IsCollapsed");
            if (attrIsCollapsed != null)
            {
                this.isCollapsed = bool.Parse(attrIsCollapsed.Value);
                this.RefreshIsCollapsed();
            }

            RefreshSubPanelRelatios();
        }

        /// <summary>
        /// SubPanels属性用以在公式各层间导航，不是所有公式内部都嵌入子面板，
        /// 因此这个方法可能没有代码。
        /// 
        /// 在实际公式类，此一方法应设置：FirstSubPanel/LastSubPanel/SubPanels这三个属性的值。
        /// </summary>
        protected override void RefreshSubPanelRelatios()
        {
            this.SubPanels.Clear();// 此方法可能被重复调用。

            if (this.basePanel.Orientation == Orientation.Horizontal)
            {
                this.firstSubPanel = this.masterPanel;
                this.lastSubPanel = this.slavePanel;

                this.SubPanels.Add(this.FirstSubPanel);
                this.SubPanels.Add(this.LastSubPanel);

                this.masterPanel.BottomSubPanel = null;
                this.masterPanel.RightSubPanel = this.slavePanel;

                this.slavePanel.TopSubPanel = null;
                this.slavePanel.LeftSubPanel = this.masterPanel;

                //考虑翻转：
                this.masterPanel.LeftSubPanel = null;
                this.slavePanel.RightSubPanel = null;
            }
            else
            {
                this.firstSubPanel = this.masterPanel;
                this.lastSubPanel = this.slavePanel;

                this.SubPanels.Add(this.FirstSubPanel);
                this.SubPanels.Add(this.LastSubPanel);

                this.masterPanel.BottomSubPanel = this.slavePanel;
                this.masterPanel.RightSubPanel = null;

                this.slavePanel.TopSubPanel = this.masterPanel;
                this.slavePanel.LeftSubPanel = null;

                //考虑翻转：
                this.masterPanel.TopSubPanel = null;
                this.slavePanel.BottomSubPanel = null;
            }
        }

        /// <summary>
        /// 翻转主、从子面板。
        /// </summary>
        public override void TurnOffMSPanel()
        {
            RunTurnOff();

            ModifingItem mi = new ModifingItem();
            Action action = new Action(this.ExID, this.ParentPanel.BasePanel.Children.IndexOf(this),
                this.GetType().Name, "TurnOffMSPanel", null, null);
            mi.Add(action);
            Editor.Do(mi);
        }

        protected override void RunTurnOff()
        {
            if (masterPanel == null || slavePanel == null) return;

            this.basePanel.Children.Remove(masterPanel);
            this.basePanel.Children.Remove(slavePanel);

            this.basePanel.Children.Insert(0, slavePanel);
            this.basePanel.Children.Insert(2, masterPanel);

            SubPanel temp = this.masterPanel;
            this.masterPanel = this.slavePanel;
            this.slavePanel = temp;

            this.masterPanel.XmlData.SetAttribute("Location", "Master");
            this.slavePanel.XmlData.SetAttribute("Location", "Slave");

            RefreshSubPanelRelatios();

            switch (bPanel.Location)
            {
                case BracketPanel.BracketLocation.Left:
                    {
                        bPanel.Location = BracketPanel.BracketLocation.Right; break;
                    }
                case BracketPanel.BracketLocation.Right:
                    {
                        bPanel.Location = BracketPanel.BracketLocation.Left; break;
                    }
                case BracketPanel.BracketLocation.Top:
                    {
                        bPanel.Location = BracketPanel.BracketLocation.Bottom; break;
                    }
                case BracketPanel.BracketLocation.Bottom:
                    {
                        bPanel.Location = BracketPanel.BracketLocation.Top; break;
                    }
            }

            bPanel.RefreshBracketPath();
            Editor.IsModified = true;
        }

        public override string CommentText
        {
            get
            {
                return base.CommentText;
            }
            set
            {
                base.CommentText = value;
                if (isCollapsed && exCollapseMark != null)
                {
                    exCollapseMark.RefreshExCollpseMarkText();
                }
            }
        }

        #region ICollpased接口的实现代码。

        private ExCollapseMark exCollapseMark;

        private bool isCollapsed = false;

        public bool IsCollapsed
        {
            get { return isCollapsed; }
            set
            {
                isCollapsed = value;
                RefreshIsCollapsed();

                this.XmlData.SetAttribute("IsCollapsed", isCollapsed.ToString());

                Editor.IsModified = true;
            }
        }

        private void RefreshIsCollapsed()
        {
            if (isCollapsed)
            {
                if (exCollapseMark == null)
                {
                    exCollapseMark = new ExCollapseMark(this);
                }

                exCollapseMark.RefreshExCollpseMarkText();
                this.mainBorder.Child = exCollapseMark;
            }
            else
            {
                this.mainBorder.Child = basePanel;
                this.exCollapseMark = null;
            }

            this.InvalidateVisual();
        }

        #endregion

        public override void SetProperty(string propertyName, string value)
        {
            if (propertyName == null || propertyName.Length <= 0) return;
            base.SetProperty(propertyName, value);

            switch (propertyName)
            {
                //case "Indent":
                //    {
                //        this.Indent = int.Parse(value);
                //        break;
                //    }
                case "Direction":
                    {
                        switch (value)
                        {
                            case "Horizontal":
                                {
                                    this.Direction = Orientation.Horizontal;
                                    break;
                                }
                            default:
                                {
                                    this.Direction = Orientation.Vertical;
                                    break;
                                }
                        }
                        break;
                    }
                case "IsCollapsed":
                    {
                        this.IsCollapsed = bool.Parse(value);
                        break;
                    }
            }
        }
    }
}
